#include "gplib.h"
#include <math.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#define PI 3.14159265358979323846

extern const int g_nByteOffset[4];


int SetPixel8(TGraphicContext *ctx, int nX, int nY, char Color)
{

	if (nX<0 || nY<0 || nX>ctx->nScreenSizeX || nY>ctx->nScreenSizeY) {
		return GP_ERR;
	}
	*BYTE_REORDER(ctx->pData+nY*ctx->nScreenSizeX+nX)=Color;
	return GP_OK;
}
/*
Отрисовка окружностей, дуг и кругов, тестируется, только 8 бит
*/
/**
 * Circle - отрисовка окружности.
 * @param x - х-координата центра окружности.
 * @param y - у-координата центра окружности.
 * @param r - радиус окружности.
 * @param color - цвет линии.
 * */
void Circle(TGraphicContext* ctx, int x,int y,int r,char color)
{

  int cx=0;
  int cy=r;
  int d=4+(2*r-1)*(2*r-1)-4*r*r;
  int dx=0;
  int dy=r*r;

/*   massert(x+r<ScreenSizeX);
   massert(y+r<ScreenSizeY);
   massert(x-r>=0);
   massert(y-r>=0);*/
  if(x+r<0 || y+r<0 || x-r>ctx->nScreenSizeX || y-r>ctx->nScreenSizeY)//не рисуем только если ни один фрагмент окружности не попадает в экран
	  return;
   while(dx<=dy)
   { // if(cnt==0)
	   //Проверки добавлены предварительно
    	 SetPixel8(ctx,x+cx,y-cy,color);
         SetPixel8(ctx,x+cy,y-cx,color);
         SetPixel8(ctx,x-cx,y-cy,color);
         SetPixel8(ctx,x-cy,y+cx,color);
         SetPixel8(ctx,x-cx,y+cy,color);
         SetPixel8(ctx,x+cy,y+cx,color);
         SetPixel8(ctx,x+cx,y+cy,color);
         SetPixel8(ctx,x-cy,y-cx,color);

      if(d>0)
      {  d+=8*(1-cy);
         cy--;
         dy-=2*cy+1;
      }
      d+=4*(2*cx+3);
      cx++;
      dx+=2*cx+1;
//      cnt--;
   }
   SetPixel8(ctx,x+cx,y-cy,color);
   SetPixel8(ctx,x-cx,y-cy,color);
   SetPixel8(ctx,x-cx,y+cy,color);
   SetPixel8(ctx,x+cx,y+cy,color);
}


/**
 * FillCircle - закраска круга.
 * @param x - х-координата центра круга.
 * @param y - у-координата центра круга.
 * @param r - радиус круга.
 * @param color - цвет круга.
 * */
void FillCircle(TGraphicContext* ctx, int x,int y,int r,char color)
{ int cx=0;
  int cy=r;
  int d=4+(2*r-1)*(2*r-1)-4*r*r;
  int dx=0;
  int dy=r*r;
  int i=0;
  char* pLine1Data;
  char* pLine2Data;
  char* pScreenData=ctx->pData;
  int ScreenByteWidth=ctx->nBytesPerLine;
  //int ScreenHeight=ctx->nScreenSizeY;
   if(x+r > ctx->nScreenSizeX || x-r < 0 || y+r > ctx->nScreenSizeY || y-r < 0)
	   return;
   while(dx<=dy)
   {
	  pLine1Data=pScreenData+(y-cx)*ScreenByteWidth+x-cy;
	  for(i=0;i<2*cy;i++,pLine1Data++)
	   	  *(BYTE_REORDER(pLine1Data))=color;
      if(cx!=0)
      {
		pLine1Data=pScreenData+(y+cx)*ScreenByteWidth+x-cy;
			  for(i=0;i<2*cy;i++,pLine1Data++)
			   	  *(BYTE_REORDER(pLine1Data))=color;
      }
      if(d>0)
      {
		 pLine1Data=pScreenData+(y-cy)*ScreenByteWidth+x-cx;
    	 pLine2Data=pScreenData+(y+cy)*ScreenByteWidth+x-cx;
		 for(i=0;i<2*cx;i++,pLine1Data++,pLine2Data++)
		 {
		     *(BYTE_REORDER(pLine1Data))=color;
		     *(BYTE_REORDER(pLine2Data))=color;
		 }
         d+=8*(1-cy);
         cy--;
         dy-=2*cy+1;
      }
      d+=4*(2*cx+3);
      cx++;
      dx+=2*cx+1;
   }
   pLine1Data=pScreenData+(y-cx)*ScreenByteWidth+x-cx;
   for(i=0;i<cx+cy;i++,pLine1Data++)
      *(BYTE_REORDER(pLine1Data))=color;
   pLine1Data=pScreenData+(y+cx)*ScreenByteWidth+x-cy;
   for(i=0;i<2*cy;i++,pLine1Data++)
   	  *(BYTE_REORDER(pLine1Data))=color;
}

int roundi(double x)
{  if(x<0) return (int)(x-0.5);
   else return (int)(x+0.5);
}
/**
 * Arc - отрисовка дуги окружности.
 * @param ctx - указатель на графический контекст.
 * @param xc - x-координата центра дуги.
 * @param yc - y-координата центра дуги.
 * @param r - радиус дуги.
 * @param sa - начальный угол дуги в радианах.
 * @param ea - конечный угол дуги в радианах.
 * @param color - цвет линиии дуги.
 * */
void Arc(TGraphicContext* ctx,int xc,int yc,int r,double sa,double ea,char color)
{

   int S0a,S1a,S2a,S3a,S4a,S5a,S6a,S7a;
   int S0b,S1b,S2b,S3b,S4b,S5b,S6b,S7b;
   int x,y,g,dx,dxdy;
   int Dxa,Dya,Dxb,Dyb;
   int small;

//   massert(x+r<ScreenSizeX);
//   massert(y+r<ScreenSizeY);
//   massert(x-r>=0);
//   massert(y-r>=0);

   // get start and stop angles from user
   if (ea < sa)
	   ea=ea+2*PI;
   if ((ea - sa) < PI)
	   small = 1;
   else small = 0;

   // initialize line draw variables for arc boundary lines
   Dxa = roundi(1000*sin(sa));
   Dya = roundi(1000*cos(sa));
   Dxb = roundi(1000*sin(ea));
   Dyb = roundi(1000*cos(ea));

   // initialize circle draw variables
   x = 0;
   y = r;
   g = 3 - (r << 1);
   dxdy = 10 - (r << 2);
   dx = 6;

   // initialize line variables
   S1a = S2a = r*Dxa;
   S5a = S6a = -S1a;
   S3a = S4a = r*Dya;
   S0a = S7a = -S3a;
   S1b = S2b = r*Dxb;
   S5b = S6b = -S1b;
   S3b = S4b = r*Dyb;
   S0b = S7b = -S3b;

   // main circle (arc) routine
   while(x <= y) {
      if (small)
      {
         if (S1a > 0 && S1b < 0)
            SetPixel8(ctx,xc+y,yc+x,color);
         if (S2a > 0 && S2b < 0)
            SetPixel8(ctx,xc+y,yc-x,color);
         if (S6a > 0 && S6b < 0)
            SetPixel8(ctx,xc-y,yc+x,color);
         if (S5a > 0 && S5b < 0)
            SetPixel8(ctx,xc-y,yc-x,color);

         if (S0a > 0 && S0b < 0)
            SetPixel8(ctx,xc+x,yc+y,color);
         if (S3a > 0 && S3b < 0)
            SetPixel8(ctx,xc+x,yc-y,color);
         if (S7a > 0 && S7b < 0)
            SetPixel8(ctx,xc-x,yc+y,color);
         if (S4a > 0 && S4b < 0)
            SetPixel8(ctx,xc-x,yc-y,color);
      }
      else
      {
         if (S1a > 0 || S1b < 0)
            SetPixel8(ctx,xc+y,yc+x,color);
         if (S2a > 0 || S2b < 0)
            SetPixel8(ctx,xc+y,yc-x,color);
         if (S6a > 0 || S6b < 0)
            SetPixel8(ctx,xc-y,yc+x,color);
         if (S5a > 0 || S5b < 0)
            SetPixel8(ctx,xc-y,yc-x,color);

         if (S0a > 0 || S0b < 0)
            SetPixel8(ctx,xc+x,yc+y,color);
         if (S3a > 0 || S3b < 0)
            SetPixel8(ctx,xc+x,yc-y,color);
         if (S7a > 0 || S7b < 0)
            SetPixel8(ctx,xc-x,yc+y,color);
         if (S4a > 0 || S4b < 0)
            SetPixel8(ctx,xc-x,yc-y,color);
      }
      if (g >= 0) {
         g += dxdy;
         dxdy += 8;
         y--;
         S0a += Dya;
         S1a -= Dxa;
         S2a -= Dxa;
         S3a -= Dya;
         S4a -= Dya;
         S5a += Dxa;
         S6a += Dxa;
         S7a += Dya;
         S0b += Dyb;
         S1b -= Dxb;
         S2b -= Dxb;
         S3b -= Dyb;
         S4b -= Dyb;
         S5b += Dxb;
         S6b += Dxb;
         S7b += Dyb;
      }
      else {
         g += dx;
         dxdy += 4;
      }
      dx += 4;
      x++;
      S0a += Dxa;
      S1a -= Dya;
      S2a += Dya;
      S3a += Dxa;
      S4a -= Dxa;
      S5a += Dya;
      S6a -= Dya;
      S7a -= Dxa;
      S0b += Dxb;
      S1b -= Dyb;
      S2b += Dyb;
      S3b += Dxb;
      S4b -= Dxb;
      S5b += Dyb;
      S6b -= Dyb;
      S7b -= Dxb;
   }
}

